package com.quectel.taskserver.job.patrol;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.func.LambdaUtil;
import com.quectel.business.common.dept.DeptPersonMsgBusiness;
import com.quectel.business.common.util.sys.SysCodeUtils;
import com.quectel.constant.PushConstants;
import com.quectel.constant.core.dept.DeptPersonMsgConstants;
import com.quectel.constant.core.securitypatrol.SecurityPatrolEventReportConstants;
import com.quectel.constant.core.securitypatrol.SecurityPatrolTaskConstants;
import com.quectel.constant.sys.SysCodeKeyConstants;
import com.quectel.core.module.dept.dto.DeptPersonDto;
import com.quectel.core.module.dept.service.DeptPersonService;
import com.quectel.core.module.device.dto.DeviceDto;
import com.quectel.core.module.securitypatrol.dto.*;
import com.quectel.core.module.securitypatrol.service.*;
import com.quectel.util.common.DateUtils;
import com.quectel.util.common.JacksonUtils;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.shardingsphere.elasticjob.api.ShardingContext;
import org.apache.shardingsphere.elasticjob.simple.job.SimpleJob;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

import static cn.hutool.core.text.CharSequenceUtil.splitTrim;

/**
 * 根据安保巡更计划生成任务
 *
 * @author bob
 * @email bob.yu@quectel.com
 * <p>
 * 1.查询所有的巡检计划
 * 2.任务内若多个时间段，对不同时间段生成当天的多个时段的任务
 * 3.通过单个任务去生成任务和点位关系表记录,并且把status设置为-1   security_patrol_task_route
 * 4.根据security_patrol_task_route 表里的deviceId 去 查询 deviceId和项目的关系表。根
 * 5.据deviceId.subjectId 关系提前生成上报记录，status也填充为-1
 * 6.生成时候增加任务开始结束时间,移动端接口卡时间
 */
@Component
public class SecurityPatrolGenerateTask implements SimpleJob {

    private static final Logger LOGGER = LoggerFactory.getLogger(SecurityPatrolGenerateTask.class);

    @DubboReference
    private SecurityPatrolPlanService securityPatrolPlanService;
    @DubboReference
    private SecurityPatrolTaskService securityPatrolTaskService;
    @DubboReference
    private SecurityPatrolEventReportService securityPatrolEventReportService;
    @DubboReference
    private SecurityPatrolSubjectService securityPatrolSubjectService;
    @DubboReference
    private DeptPersonService deptPersonService;
    @DubboReference
    private SecurityPatrolTaskRouteService securityPatrolTaskRouteService;
    @DubboReference
    private SecurityPatrolDeviceSubjectService securityPatrolDeviceSubjectService;

    @Autowired
    private DeptPersonMsgBusiness deptPersonMsgBusiness;

    @Override
    public void execute(ShardingContext shardingContext) {
        securityPatrolGenerateTask();
    }

    public void securityPatrolGenerateTask() {
        LOGGER.info("安保巡更任务开始执行... 时间 {} 下面各个机器开始抢占执行",
                DateUtils.getCurrentDateStr(DateUtils.FormatType.COMMON));
        Date nextDate = new Date(System.currentTimeMillis() + 24L * 60 * 60 * 1000);
        String nextDay = new SimpleDateFormat(DateUtils.FormatType.SIMPLE.getType())
                .format(nextDate);
        Date now = new Date();
        //抢占执行生成任务
        LOGGER.info("本次本台机器可以执行生成任务,要生成{}的巡更任务", nextDay);

        List<SecurityPatrolPlanDto> result = new ArrayList<>();
        int pageNo = 1;
        while (true) {
            Map<String, Object> queryMap = new HashMap<>();
            queryMap.put("startTime", nextDay);
            queryMap.put("endTime", nextDay);
            queryMap.put("offset", (pageNo - 1) * 2000);
            queryMap.put("limit", 2000);
            List<SecurityPatrolPlanDto> list = securityPatrolPlanService.queryList(queryMap);
            if (list.size() <= 0) {
                break;
            }
            result.addAll(list);
            pageNo++;
        }
        LOGGER.info("要执行巡更计划的条数{}", result.size());
        for (SecurityPatrolPlanDto securityPatrolPlanDto : result) {
            if (StringUtils.isNotBlank(securityPatrolPlanDto.getWeekPlan())) {
                Calendar calendar = Calendar.getInstance();
                calendar.setTime(nextDate);
                int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);
                if (dayOfWeek - 1 == 0) {
                    dayOfWeek = 7;
                } else {
                    dayOfWeek--;
                }
                List<String> weekPlan = JacksonUtils.parseArray(securityPatrolPlanDto.getWeekPlan(), String.class);
                if (!weekPlan.contains(dayOfWeek + "")) {
                    // 日期不满足
                    continue;
                }

                if (StringUtils.isNotBlank(securityPatrolPlanDto.getDayPeriodArr())) {
                    List<String> parseArray = JacksonUtils.parseArray(securityPatrolPlanDto.getDayPeriodArr(), String.class);
                    for (String period : parseArray) {
                        try {
                            // 针对每个时间段生成
                            SecurityPatrolTaskDto securityPatrolTaskDto = new SecurityPatrolTaskDto();

                            List<DeviceDto> deviceDtos = securityPatrolPlanDto.getSecurityPatrolRouteDto().getDeviceDtoList();
                            if (CollectionUtils.isEmpty(deviceDtos)) {
                                break;
                            }

                            securityPatrolTaskDto.setTenantId(securityPatrolPlanDto.getTenantId());
                            securityPatrolTaskDto.setVillageId(securityPatrolPlanDto.getVillageId());
                            securityPatrolTaskDto.setCategory(securityPatrolPlanDto.getCategory());
                            securityPatrolTaskDto.setPlanId(securityPatrolPlanDto.getId());
                            securityPatrolTaskDto.setPlanName(securityPatrolPlanDto.getName());
                            securityPatrolTaskDto.setName(
                                    String.format("%s-%s-%s", nextDay, securityPatrolPlanDto.getName(), period)
                            );
                            securityPatrolTaskDto.setExecUserId(securityPatrolPlanDto.getExecUserId());
                            securityPatrolTaskDto.setExecUsername(securityPatrolPlanDto.getExecUsername());
                            securityPatrolTaskDto.setDate(nextDay);
                            securityPatrolTaskDto.setPeriod(period);
                            List<String> datePeriod = splitTrim(period, "-");
                            List<String> collect = datePeriod.stream()
                                    .map(v -> nextDay + " " + v + ":00")
                                    .collect(Collectors.toList());

                            securityPatrolTaskDto.setExecStartTime(DateUtil.parse(collect.get(0), DateUtils.FormatType.COMMON.getType()));
                            securityPatrolTaskDto.setExecEndTime(DateUtil.parse(collect.get(1), DateUtils.FormatType.COMMON.getType()));

                            if (securityPatrolPlanDto.getSecurityPatrolRouteDto() != null) {
                                List<String> deviceIds = JacksonUtils.parseArray(securityPatrolPlanDto.getSecurityPatrolRouteDto().getRouteArr(), String.class);
                                // 巡检点位数
                                securityPatrolTaskDto.setRouteCount(deviceIds.size());
                                securityPatrolTaskDto.setExecCount(0);
                            }
                            // 任务多状态赋空
                            List<String> taskStatusList = new ArrayList<>();
                            securityPatrolTaskDto.setRouteExecTotalStatus(JacksonUtils.toJsonString(taskStatusList));
                            securityPatrolTaskDto.setExecStatus((byte) 0);
                            securityPatrolTaskDto.setCreateTime(now);
                            Long taskId = securityPatrolTaskService.save(securityPatrolTaskDto);

                            // task route 表 生成点位记录
                            for (DeviceDto deviceDto : deviceDtos) {
                                SecurityPatrolTaskRouteDto securityPatrolTaskRouteDto
                                        = new SecurityPatrolTaskRouteDto();
                                securityPatrolTaskRouteDto.setTaskId(taskId);
                                securityPatrolTaskRouteDto.setCategory(securityPatrolPlanDto.getCategory());
                                securityPatrolTaskRouteDto.setTaskName(securityPatrolTaskDto.getName());
                                securityPatrolTaskRouteDto.setDeviceId(deviceDto.getId());
                                // 定时任务状态填充 -1
                                securityPatrolTaskRouteDto.setStatus(SecurityPatrolEventReportConstants.ReportStatusEnum.NOT_CHANGED.getStatus());
                                Long taskRouteId = securityPatrolTaskRouteService.save(securityPatrolTaskRouteDto);

                                // 提前生成上报记录
                                Map<String, Object> queryParams = new HashMap<>();
                                queryParams.put(LambdaUtil.getFieldName(SecurityPatrolDeviceSubjectDto::getDeviceId), deviceDto.getId());
                                List<SecurityPatrolDeviceSubjectDto> securityPatrolDeviceSubjectDtos = securityPatrolDeviceSubjectService.queryList(queryParams);
                                for (SecurityPatrolDeviceSubjectDto securityPatrolDeviceSubjectDto : securityPatrolDeviceSubjectDtos) {
                                    SecurityPatrolEventReportDto reportDto = new SecurityPatrolEventReportDto();
                                    reportDto.setTaskName(securityPatrolTaskDto.getName());
                                    reportDto.setVillageId(securityPatrolTaskDto.getVillageId());
                                    reportDto.setTenantId(securityPatrolPlanDto.getTenantId());
                                    reportDto.setCategory(securityPatrolPlanDto.getCategory());
                                    reportDto.setTaskRouteId(taskRouteId);
                                    reportDto.setSubjectName(securityPatrolSubjectService.selectCacheById(securityPatrolDeviceSubjectDto.getSubjectId()).getSubject());
                                    reportDto.setSubjectId(securityPatrolDeviceSubjectDto.getSubjectId());

                                    // 上报部分需要按巡检项目类型过滤，新增此字段
                                    SecurityPatrolSubjectDto securityPatrolSubjectDto = securityPatrolSubjectService.selectCacheById(securityPatrolDeviceSubjectDto.getSubjectId());
                                    if (securityPatrolSubjectDto != null) {
                                        reportDto.setGroupType(securityPatrolSubjectDto.getGroupType());

                                    }

                                    reportDto.setReportUserId(securityPatrolTaskDto.getExecUserId());
                                    reportDto.setReportUsername(securityPatrolTaskDto.getExecUsername());
                                    reportDto.setStatus(SecurityPatrolEventReportConstants.ReportStatusEnum.NOT_CHANGED.getStatus());
                                    List<String> list = new ArrayList<>();
                                    reportDto.setSnapshotImg(JacksonUtils.toJsonString(list));
                                    securityPatrolEventReportService.save(reportDto);
                                }
                            }

                            // 发消息通知第二天执行的巡更任务
                            DeptPersonDto deptPersonDto = deptPersonService.selectById(securityPatrolTaskDto.getExecUserId());
                            DeptPersonMsgConstants.SourceType securityPatrolMsg = null;
                            // 安防巡检
                            if (securityPatrolTaskDto.getCategory().equals(SecurityPatrolTaskConstants.TaskCategoryEnum.SECURITY_PATROL.getTaskCategory())) {
                                securityPatrolMsg = DeptPersonMsgConstants.SourceType.SECURITY_PATROL_MSG;
                            }

                            if (null != deptPersonDto) {
                                deptPersonMsgBusiness.pushMsg(
                                        new ArrayList<>(Arrays.asList(deptPersonDto)),
                                        securityPatrolMsg,
                                        taskId,
                                        null,
                                        String.format(SecurityPatrolTaskConstants.SECURITY_PATROL_PUSH_MSG_TEMPLATE,
                                                securityPatrolTaskDto.getName(), securityPatrolTaskDto.getDate(), securityPatrolTaskDto.getPeriod()),
                                        true,
                                        new PushConstants.PushType[]{PushConstants.PushType.WECHAT_OFFICIAL});
                                LOGGER.info("向{}推动次日{}巡检任务成功", deptPersonDto.getName(), SysCodeUtils.easyToGetName(SysCodeKeyConstants.PATROL_GROUP_CATEGORY, String.valueOf(securityPatrolPlanDto.getCategory())));
                                securityPatrolTaskDto.setId(taskId);
                                securityPatrolTaskDto.setIsPush(SecurityPatrolTaskConstants.IsPushedEnum.IS_PUSHED.getIsPushed());
                                securityPatrolTaskService.updateById(securityPatrolTaskDto);
                            } else {
                                LOGGER.info("向{}推动次日{}巡检任务失败", deptPersonDto.getName(), SysCodeUtils.easyToGetName(SysCodeKeyConstants.PATROL_GROUP_CATEGORY, String.valueOf(securityPatrolPlanDto.getCategory())));
                                securityPatrolTaskDto.setId(taskId);
                                securityPatrolTaskDto.setIsPush(SecurityPatrolTaskConstants.IsPushedEnum.IS_NOT_PUSHED.getIsPushed());
                                securityPatrolTaskService.updateById(securityPatrolTaskDto);
                            }
                        } catch (Exception e) {
                            continue;
                        }

                    }
                }
            }
        }
        LOGGER.info("{}安保巡更任务已生成完毕", nextDay);
    }


}